# -*- encoding: utf-8 -*-

from odoo.addons.base_cw.public import merge_line

from odoo import models, fields, api, _
from odoo.addons import base_cw
from odoo.exceptions import  UserError


class AccountPay(models.Model):
    _name = 'account.pay'
    _inherit = ['account.pay', 'account.voucher.script']
    _description = u'付款单'

    script_line_ids = fields.One2many('account.voucher.script.line', 'ap_id', u'预切凭证明细')
    is_summary_generate_voucher = fields.Boolean(u'汇开凭证', default=False)
    cash_dialy_ids = fields.One2many('account.cash.dialy', 'pay_order_id', string='出纳日记账')

    def action_done(self):
        super(AccountPay, self).action_done()
        for record in self:
            for pay_line in record.line_ids:
                # 创建汇票
                if pay_line.money_order:
                    if pay_line.amount <= pay_line.money_order.money_order_money:
                        pay_line.env['money.order.line'].create(dict(
                            drawer=pay_line.drawer.id,
                            transfer_partner_id=pay_line.transfer_partner_id.id,
                            partner_bank_id=pay_line.partner_bank_id.id,
                            payee=pay_line.payee.id,
                            # transfer_for_partner_id=pay_line.transfer_for_partner_id.id,
                            transfer_money=pay_line.amount,
                            money_order_id=pay_line.money_order.id,
                            payment_line_id=pay_line.id,
                            payment_date=fields.date.today(),
                            payment_id=record.id,
                            payment_voucher_id=record.voucher_id.id if record.voucher_id else False
                        ))
                    else:
                        raise UserError('付款金额必须小于或等于汇票金额')

    @api.model
    def get_account(self, type_t):
        """
        取预收、预付会计科目
        :return:
        """

        config = self.env['account.voucher.template'].search([('code', '=', '01')], limit=1)
        if not config or not config.advance_account_id or not config.prepaid_account_id:
            raise UserError(_(u'请在财务{凭证模版}设定中 维护预收、预付会计科目!'))
        if type_t == 'advance':
            account_id = config.advance_account_id.id
        elif type_t == 'prepaid':
            account_id = config.prepaid_account_id.id
        else:
            pass
        return account_id

    def action_confirm(self):
        for pay in self:
            pay.generate_account_voucher_script()
        super(AccountPay, self).action_confirm()

    def action_cancel_confirm(self):
        for pay in self:
            pay.generate_cancel_voucher_script()
        super(AccountPay, self).action_cancel_confirm()

    def action_cancel_done(self):
        super(AccountPay, self).action_cancel_done()
        for record in self:
            if record.voucher_id.line_ids and record.voucher_id.state not in ('draft', 'cancel',):
                raise UserError(_(u'已经生成凭证内容，请先取消凭证明细再取消当前收款。'))
            money_order_line_ids = record.env['money.order.line'].search([('payment_id', '=', record.id)])
            for money_order_line in money_order_line_ids:
                money_order_line.unlink()

    def generate_account_voucher_script(self):
        self.ensure_one()
        self.generate_account_voucher_script_line()

    def generate_account_voucher(self):
        """继承创建凭证的方法，给凭证增加关联到付款单上的字段"""
        super(AccountPay, self).generate_account_voucher()
        for record in self:
            if record.voucher_id:
                record.voucher_id.account_pay_id = record.id
                money_order_line_ids = record.env['money.order.line'].search([('payment_id', '=', record.id)])
                for money_order_line in money_order_line_ids:
                    money_order_line.write(dict(
                        payment_voucher_id=record.voucher_id.id
                    ))

    def generate_cancel_voucher_script(self):
        '''
        取消生成的凭证
        :return:
        '''
        for pay in self:
            if pay.voucher_id and pay.voucher_id.state not in ('draft', 'cancel'):
                raise UserError(_(u'错误提示当前付款单生成的凭证已经确认，不能取消！'))
            if pay.voucher_id:
                pay.voucher_id.line_ids.unlink()
                pay.voucher_id = False
            pay.script_line_ids.unlink()

    def generate_account_voucher_script_line(self):
        """
        产生预切凭证明细
        :return:
        """
        for pay in self:
            pay.script_line_ids = False
            # 1.借方
            pays = pay.line_ids.filtered(lambda x: x.payment_category_id.is_payment)
            name = pays and pays[0].partner_bank_id and (pays[0].partner_bank_id.name or pays[0].partner_bank_id.bank_id.name) + ":" + pays[
                0].partner_bank_id.acc_number or False
            items = []
            d_items = []
            if pay.payment_type == 'B':  # u'预付款'
                account_id = self.get_account('prepaid'),
                c_item = dict(dc_type='D',
                              account_id=account_id,
                              credit=pay.payment_amount,
                              lc_credit=pay.local_payment_amount,
                              currency_id=pay.currency_id and pay.currency_id.id or False,
                              exchange_rate=pay.currency_id and pay.currency_id.rate or 1.0,
                              name=pay.note or name
                              )
                d_account = self.env['cncw.account'].browse(account_id)
                if d_account.sub_account_type == 'has':
                    sub_account_lines_data = []
                    # 判断是否存在供应商类型辅助核算
                    d_sub_category = d_account.subaccount_category_ids.filtered(lambda categ: categ.code == 'supplier')
                    if d_sub_category:
                        line_data = {'category_id': d_sub_category[0].id,
                                     # 若科目中存在辅助核算，取辅助核算第一个，若没有取当前用户
                                     'sub_account_id': pay.partner_id and pay.partner_id.id or False}
                # if self.env['cncw.account'].browse(account_id).sub_account_type == 'has':
                #     sub_account_lines_data = []
                #
                #     for line in self.env['cncw.account'].browse(account_id).subaccount_category_ids:
                #         line_data = {'category_id': line.id,
                #                      # 若科目中存在辅助核算，取辅助核算第一个，若没有取当前用户
                #                      'sub_account_id': pay.partner_id and pay.partner_id.id or False} # pay.partner_id and pay.partner_id.id or False
                        # line.sub_account_ids[0].id if line.sub_account_ids
                        # else pay.partner_id and pay.partner_id.id or False
                        sub_account_lines_data.append((0, 0, line_data))

                    # if sub_account_lines_data:
                    #     for sub_account_line_data in sub_account_lines_data:
                    #         if sub_account_line_data[2] and sub_account_line_data[2].get(
                    #                 'sub_account_id') != pay.partner_id.id:
                    #             sub_account_lines_data.append(
                    #                 (0, 0, {'category_id': pay.partner_id.subaccount_category_id.id,
                    #                         'sub_account_id': pay.partner_id and pay.partner_id.id or False}))
                    c_item.update(dict(
                        sub_account_id=pay.partner_id and pay.partner_id.id or False,
                        sub_account_lines=sub_account_lines_data
                    ))
                d_items.append((0, 0, c_item))
            else:
                for x in pay.offset_line_ids:
                    d_item = dict(dc_type=x.dc_type,
                                  account_id=x.account_id.id,
                                  debit=x.amount,
                                  lc_debit=x.local_amount,
                                  currency_id=x.master_id.currency_id and x.master_id.currency_id.id or False,
                                  exchange_rate=x.master_id.currency_id and x.master_id.currency_id.rate or 1.0,
                                  name=pay.note or name
                                  )
                    if x.account_id.sub_account_type == 'has':
                        sub_account_lines_data = []
                        for line in x.sub_account_lines:
                            line_data = {'category_id': line.category_id.id, 'sub_account_id': line.sub_account_id.id}
                            sub_account_lines_data.append((0, 0, line_data))
                        if sub_account_lines_data:
                            for sub_account_line_data in sub_account_lines_data:
                                if sub_account_line_data[2] and sub_account_line_data[2].get(
                                        'sub_account_id') != pay.partner_id.id:
                                    sub_account_lines_data.append(
                                        (0, 0, {'category_id': pay.partner_id.subaccount_category_id.id,
                                                'sub_account_id': pay.partner_id and pay.partner_id.id or False}))
                        d_item.update(dict(
                            sub_account_id=x.sub_account_id and x.sub_account_id.id or False,
                            sub_account_lines=sub_account_lines_data
                        ))
                    d_items.append((0, 0, d_item))

            # 1.贷方
            c_items = []
            for x in pay.line_ids:
                c_item = dict(dc_type=x.dc_type,
                              account_id=x.account_id.id,
                              debit=x.amount if x.dc_type == 'D' else 0,
                              lc_debit=x.local_amount if x.dc_type == 'D' else 0,
                              credit=x.amount if x.dc_type == 'C' else 0,
                              lc_credit=x.local_amount if x.dc_type == 'C' else 0,
                              currency_id=x.master_id.currency_id and x.master_id.currency_id.id or False,
                              exchange_rate=x.master_id.currency_id and x.master_id.currency_id.rate or 1.0,
                              name=x.note or (name if not x.payment_category_id.is_payment else ''))
                if x.partner_bank_id:
                    c_item.update({'name': (x.partner_bank_id.name or x.partner_bank_id.bank_id.name) + ':' + x.partner_bank_id.acc_number})

                sub_account_lines_data = []
                if len(x.sub_account_lines) > 0:
                    for line in x.sub_account_lines:
                        line_data = {'category_id': line.category_id.id,
                                     'sub_account_id': line.sub_account_id.id}
                        sub_account_lines_data.append((0, 0, line_data))
                else:
                    if x.account_id.sub_account_type == 'has':

                        # 判断是否存在银行类型辅助核算
                        c_sub_category = x.account_id.subaccount_category_ids.filtered(lambda categ: categ.code == 'bank')
                        if c_sub_category:
                            line_data = {'category_id': c_sub_category[0].id,
                                         'sub_account_id': c_sub_category[0].sub_account_ids[0].id}
                            sub_account_lines_data.append((0, 0, line_data))
                    # for line in x.sub_account_lines:
                    #     line_data = {'category_id': line.category_id.id,
                    #                  'sub_account_id': line.sub_account_id.id}
                    #     sub_account_lines_data.append((0, 0, line_data))
                    # if sub_account_lines_data:
                    #     for sub_account_line_data in sub_account_lines_data:
                    #         if sub_account_line_data[2] and sub_account_line_data[2].get(
                    #                 'sub_account_id') != pay.partner_id.id:
                    #             sub_account_lines_data.append(
                    #                 (0, 0, {'category_id': pay.partner_id.subaccount_category_id.id,
                    #                         'sub_account_id': line.sub_account_ids[0].id if line.sub_account_ids
                    #     else pay.partner_id and pay.partner_id.id or False}))
                c_item.update(dict(
                        sub_account_id=x.sub_account_id and x.sub_account_id.id or False,
                        sub_account_lines=sub_account_lines_data
                    ))
                c_items.append((0, 0, c_item))
            items += d_items + c_items
            items = merge_line(self, items)
            if items:
                pay.write(dict(script_line_ids=items))
        super(AccountPay, self).generate_account_voucher_script_line()

    def _assert_balanced(self):
        if not self.ids:
            return True
        prec = self.env['decimal.precision'].precision_get('Amount')
        # 正则小数几位
        f_rule = '%.{}f'.format(max(5, prec))
        # sql = """
        #         SELECT  master_id
        #           FROM  account_voucher_script_line
        #          WHERE  master_id in %s
        #       GROUP BY  master_id
        #         HAVING  abs(sum(debit) - sum(credit)) > %s
        #     """ % (tuple(self.ids), 10 ** (-max(5, prec)))
        self._cr.execute("""
                    SELECT ap_id
                      FROM account_voucher_script_line
                     WHERE ap_id in %s
                  GROUP BY ap_id
                    HAVING abs(sum(debit) - sum(credit)) > %s
                """, (tuple(self.ids), float(f_rule % 10 ** (-max(5, prec)))))  # 默认取六位小数  10 ** (-max(5, prec))
        if len(self._cr.fetchall()) != 0:
            raise UserError(_(u"预切凭证借贷不平，请检查."))
        return True


class account_pay_offset_line(models.Model):
    _inherit = 'account.pay.offset.line'
    _description = u'付款单冲销明细'

    @api.depends('account_id')
    def _get_sub_account_ids(self):
        for record in self:
            account_obj = self.env['cncw.account']
            record.sub_account_ids = account_obj.get_sub_account_ids(record.account_id)

    sub_account_type = fields.Selection(base_cw.public.SUB_ACCOUNT_TYPE, u'辅助核算类型',
                                        related='account_id.sub_account_type', readonly=True)
    sub_account_ids = fields.Many2many('res.partner', compute='_get_sub_account_ids', string=u'可选辅助核算')


class AccountPayLine(models.Model):
    _inherit = 'account.pay.line'
    _description = u'付款单明细'

    @api.depends('account_id')
    def _get_sub_account_ids(self):
        for record in self:
            account_obj = self.env['cncw.account']
            record.sub_account_ids = account_obj.get_sub_account_ids(record.account_id)

    sub_account_type = fields.Selection(base_cw.public.SUB_ACCOUNT_TYPE, u'辅助核算类型',
                                        related='account_id.sub_account_type', readonly=True)
    sub_account_ids = fields.Many2many('res.partner', compute='_get_sub_account_ids', string=u'可选辅助核算')
    sub_account_lines = fields.One2many('sub.account.line', 'account_pay_line_id',
                                        store=True,
                                        string=u'辅助核算')

    money_order = fields.Many2one(comodel_name='money.order', string='汇票')

    @api.onchange('money_order')
    def _onchange_money_order(self):
        for record in self:
            if record.money_order:
                record.amount = record.money_order.money_order_money

    bill_date = fields.Date(string='出票日期', related='money_order.bill_date')
    bill_due_date = fields.Date(string='票据到期日', related='money_order.bill_due_date')
    overdue_days = fields.Integer(string='汇票到期天数', related='money_order.overdue_days')
    money_order_money = fields.Monetary(string='汇票金额', related='money_order.money_order_money')
    currency_id = fields.Many2one(comodel_name='res.currency', string='币别',
                                  default=lambda self: self.env.user.company_id.currency_id)

    drawer = fields.Many2one(comodel_name='res.partner', string='出票人')
    transfer_partner_id = fields.Many2one(comodel_name='res.partner', string='背书单位', related='master_id.partner_id')
    partner_bank_id = fields.Many2one(comodel_name='res.partner.bank', string='出票银行')
    payee = fields.Many2one(comodel_name='res.partner', string='付款人', default=lambda self: self.env.company.id)
    # transfer_for_partner_id = fields.Many2one(comodel_name='res.partner', string='被背书单位')
    transfer_money = fields.Monetary(string='金额', currency_field='currency_id')

    def _compute_sub_account_lines(self):
        """在明细创建的时候给予默认的辅助核算"""
        pass
        # for record in self:
        #     if record.account_id and record.account_id.sub_account_type == 'has':
        #         for line in record.sub_account_lines:
        #             val = {'category_id': line.category_id.id, 'sub_account_id': line.sub_account_id.id}
        #         # val = {'category_id': record.master_id.partner_id.subaccount_category_id.id,
        #         #        'sub_account_id': record.master_id.partner_id.id}
        #         record.sub_account_lines = [(0, 0, val)]

    def create(self, vals):
        res = super(AccountPayLine, self).create(vals)
        res._compute_sub_account_lines()
        return res

    @api.model
    def create_account_prepaid(self):
        """
        创建 预付款单
        :return:
        or (
                        self.payment_type == 'A' and line.account_id.ap_ar_type == '10' and line.dc_type == 'D')
        """
        if self.master_id.state == 'done' and not self.prepaid_id and (self.master_id.payment_type == 'B' or (
                self.master_id.payment_type == 'A' and self.account_id.ap_ar_type in (
                '10', '11') and self.dc_type == 'D')):
            sub_account_lines_data = []
            for line2 in self.sub_account_lines:
                line_data = {'category_id': line2.category_id.id, 'sub_account_id': line2.sub_account_id.id}
                sub_account_lines_data.append((0, 0, line_data))
            # if self.master_id.partner_id:
            #     # for line in self.sub_account_lines:
            #     line_data = {'category_id': self.env.ref('base_cw.account_subaccount_category_supplier').id,
            #                  'sub_account_id': self.master_id.partner_id.id}
            #     sub_account_lines_data = [(0, 0, line_data)]
            item = dict(res_id=self.id,
                        name="New",
                        date=self.master_id.date,
                        partner_id=self.master_id.partner_id.id,
                        currency_id=self.master_id.currency_id.id,
                        exchange_rate=self.master_id.exchange_rate,
                        tax_rate=self.master_id.tax_id.amount,
                        amount=self.amount,
                        total_amount=self.amount,
                        paid_amount=0,
                        remaining_amount=self.amount,
                        lc_amount=self.local_amount,
                        lc_total_amount=self.local_amount,
                        lc_paid_amount=0,
                        lc_remaining_amount=self.local_amount,
                        dc_type=self.dc_type,
                        note=self.note,
                        account_id=self.master_id.get_account(type_t='prepaid'),
                        org_account_id=self.account_id.id,
                        sub_account_id=self.sub_account_id.id,
                        sub_account_lines=sub_account_lines_data,
                        offset_state='N')
            self.env['account.prepaid'].create(item)